[ty] Add support for properties that return Self#21335
Conversation
Diagnostic diff on typing conformance testsChanges were detected when running ty on typing conformance tests--- old-output.txt 2025-11-10 09:58:36.256463363 +0000
+++ new-output.txt 2025-11-10 09:58:39.754484899 +0000
@@ -492,8 +492,6 @@
generics_scoping.py:65:11: error[invalid-generic-class] Generic class `MyGeneric` must not reference type variables bound in an enclosing scope: `T` referenced in class definition here
generics_scoping.py:75:11: error[invalid-generic-class] Generic class `Bad` must not reference type variables bound in an enclosing scope: `T` referenced in class definition here
generics_self_advanced.py:11:24: error[invalid-return-type] Function always implicitly returns `None`, which is not assignable to return type `Self@prop1`
-generics_self_advanced.py:18:1: error[type-assertion-failure] Argument does not have asserted type `ParentA`
-generics_self_advanced.py:19:1: error[type-assertion-failure] Argument does not have asserted type `ChildA`
generics_self_advanced.py:28:25: error[invalid-return-type] Function always implicitly returns `None`, which is not assignable to return type `Self@method1`
generics_self_advanced.py:36:9: error[type-assertion-failure] Argument does not have asserted type `list[Self@method2]`
generics_self_advanced.py:37:9: error[type-assertion-failure] Argument does not have asserted type `Self@method2`
@@ -1005,5 +1003,5 @@
typeddicts_usage.py:28:17: error[missing-typed-dict-key] Missing required key 'name' in TypedDict `Movie` constructor
typeddicts_usage.py:28:18: error[invalid-key] Invalid key for TypedDict `Movie`: Unknown key "title"
typeddicts_usage.py:40:24: error[invalid-type-form] The special form `typing.TypedDict` is not allowed in type expressions. Did you mean to use a concrete TypedDict or `collections.abc.Mapping[str, object]` instead?
-Found 1007 diagnostics
+Found 1005 diagnostics
WARN A fatal error occurred while checking some files. Not all project files were analyzed. See the diagnostics list above for details.
|
|
|
| Lint rule | Added | Removed | Changed |
|---|---|---|---|
invalid-argument-type |
37 | 0 | 20 |
type-assertion-failure |
0 | 18 | 0 |
invalid-assignment |
2 | 0 | 8 |
unsupported-operator |
8 | 0 | 2 |
unresolved-attribute |
9 | 0 | 0 |
invalid-return-type |
1 | 0 | 5 |
non-subscriptable |
5 | 0 | 0 |
possibly-missing-attribute |
3 | 0 | 0 |
no-matching-overload |
2 | 0 | 0 |
not-iterable |
2 | 0 | 0 |
call-non-callable |
1 | 0 | 0 |
possibly-missing-implicit-call |
1 | 0 | 0 |
redundant-cast |
1 | 0 | 0 |
unused-ignore-comment |
0 | 1 | 0 |
| Total | 72 | 19 | 35 |
CodSpeed Performance ReportMerging #21335 will degrade performances by 8.39%Comparing Summary
Benchmarks breakdown
Footnotes
|
There was a problem hiding this comment.
How extensible will this approach be for other decorated methods, like e.g. methods decorated with functools.lru_cache? (Mind you, I don't know why a method decorated with @lru_cache would ever be annotated as returning Self, but you get the idea.)
Even if this approach won't work in other cases, though, properties are common enough that I think even a narrow fix is worthwhile for now!
04e31cf to
08bb155
Compare
I thought about this, but there was no way to test this yet. I should have commented on that, though. I have now pushed up a fix that is not specific to properties and should work for other decorators as well. The only way I can decorate a method right now without being restricted by our generics solver is to use |
* origin/main: (38 commits) [ty] Make implicit submodule imports only occur in global scope (#21370) [ty] introduce local variables for `from` imports of submodules in `__init__.py(i)` (#21173) [`ruff`] Ignore `str()` when not used for simple conversion (`RUF065`) (#21330) [ty] implement `typing.NewType` by adding `Type::NewTypeInstance` [ty] supress inlay hints for `+1` and `-1` (#21368) [ty] Use type context for inference of generic constructors (#20933) [ty] Improve generic call expression inference (#21210) [ty] supress some trivial expr inlay hints (#21367) [`configuration`] Fix unclear error messages for line-length values exceeding `u16::MAX` (#21329) [ty] Fix incorrect inference of `enum.auto()` for enums with non-`int` mixins, and imprecise inference of `enum.auto()` for single-member enums (#20541) [`refurb`] Detect empty f-strings (`FURB105`) (#21348) [ty] provide `import` completion when in `from <name> <name>` statement (#21291) [ty] elide redundant inlay hints for function args (#21365) Fix syntax error false positive on alternative `match` patterns (#21362) Add a new "Opening a PR" section to the contribution guide (#21298) [`flake8-simplify`] Fix SIM222 false positive for `tuple(generator) or None` (`SIM222`) (#21187) Rebuild ruff binary instead of sharing it across jobs (#21361) [ty] Fix `--exclude` and `src.exclude` merging (#21341) [ty] Add support for properties that return `Self` (#21335) Add upstream linter URL to `ruff linter --output-format=json` (#21316) ...
Summary
Detect usages of implicit
selfin property getters, which allows us to treat their signature as being generic.closes astral-sh/ty#1502
Typing conformance
Two new type assertions that are succeeding.
Ecosystem results
Mostly look good. There are a few new false positives related to a bug with constrained typevars that is unrelated to the work here. I reported this as astral-sh/ty#1503.
Test Plan
Added regression tests.